home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
ada
/
gwuada_4.zip
/
INT21.ASM
< prev
next >
Wrap
Assembly Source File
|
1990-07-25
|
6KB
|
273 lines
name int21
_text segment byte public 'code'
dgroup group _data,_bss
assume cs:_text,ds:dgroup
_text ends
_data segment word public 'data'
_d@ label byte
_data ends
_bss segment word public 'bss'
_b@ label byte
_bss ends
;
; I switch to my own stack when handling an int 21 request on behalf
; of a process. This is done because the amount of stack available to
; the calling process is not known. The flag "onintstack" indicates
; whether this special stack is currently in use so that we do not
; inadvertantly try to use it again. If an int 21 call is made while
; this stack is in use (as can occur for instance when we are flushing
; a buffer to disk, or calling ioctl to find out whether the current
; handle refers to the console), we do not call the C function
; "int21handler", but rather chain to DOS immediately.
;
_bss segment word public 'bss'
db 512 dup (?)
intstack label byte
_bss ends
_text segment byte public 'code'
public _grab21, _rstr21, _getpsp, _setpsp, _getdosflag, _callDOS
extrn _int21handler:near
savesp dw ? ; saved ss:sp of calling process
savess dw ?
onintstack dw ?
;
; psp = getpsp(void)
;
_getpsp proc near
mov ah, 51h
int 21h
mov ax, bx
ret
_getpsp endp
;
; void setpsp(psp)
;
; This function uses undocumented DOS function 50h
;
_setpsp proc near
push bp
mov bp, sp
mov bx, [bp+4]
mov ah, 50h
int 21h
pop bp
ret
_setpsp endp
;
; char far *dosflag = getdosflag(void);
;
; Returns a pointer to the "indos" flag. This is used to prevent
; any attempt to re-enter DOS.
;
_getdosflag proc near
mov ah,34h
int 21h
mov ax, bx
mov dx, es
ret
_getdosflag endp
;
; int grab21(void)
;
; Intercept DOS function calls by installing our own
; int 21 handler. Zero is returned if the current int 21
; handler has the same offset as the one being installed.
; This is used as a quick check to see if script
; is already active. It is far from a foolproof check,
; for instance it is possible that the DOS interrupt
; handler has the same offset as our own handler in which
; case this function would indicate that script was already
; active when in fact it was not. The probability is reasonably
; small that this won't occur.
;
_grab21 proc near
mov ax, 3521h ; save current int 21 handler
int 21h
mov word ptr cs:oldvct21, bx
mov word ptr cs:oldvct21+2, es
mov dx, offset int21 ; set up our int 21 handler
cmp bx, dx
je nogo
mov ax, 2521h
int 21h
mov cs:onintstack,0
mov ax,1
ret
nogo:
mov ax,0
ret
_grab21 endp
;
; rstr21()
;
; Repair the damage done above before exiting.
;
_rstr21 proc near
mov cs:onintstack,1
push ds
lds dx, dword ptr cs:oldvct21
mov ax, 2521h
int 21h
pop ds
ret
_rstr21 endp
;
; The int 21 first level handler.
; This function sets up a stack, pushes the processor registers
; on this stack, and then calls C. In order that the C handler
; can make DOS calls without recursing, the flag "onintstack"
; is set. If the following ISR is called when this flag is set,
; it will not call the C handler again, but instead will chain
; immediately to DOS
;
int21 proc far
cmp cs:onintstack, 0
jne chain
mov cs:onintstack, 1
mov word ptr cs:savesp, sp ; switch stacks
mov word ptr cs:savess, ss
push cs
pop ss
mov sp, offset dgroup:intstack
sti
cld
;
push es ; Save regs on the new stack.
push ds ; The C function "int21hander"
push dx ; expects the registers
push cx ; in this order.
push bx ; They must look like a
push ax ; "union MYFRAME"
push cs
pop ds
call near ptr _int21handler
mov ah,al
sahf
pop ax
pop bx
pop cx
pop dx
pop ds
pop es
;
mov cs:onintstack, 0
mov ss, word ptr cs:savess ; Restore the original stack
mov sp, word ptr cs:savesp
je chain ; Nothing between the sahf above, and here
; is allowed to affect the flags.
ret 2 ; Carry flag still set from sahf above.
chain:
db 0EAh ; opcode for FAR JUMP
oldvct21 dd ?
int21 endp
;
; flags = callDOS(regp)
; union MYFRAME *regp;
;
; This function loads the registers from "regp", executes an int 21
; and then copies the modified registers back into "regp"
; The processor flags are returned as the value of the function
;
; This function is currently used to read console input on behalf
; of a process and is called while the special stack is in use.
; This means that "onintstack" is set. A problem arises if the
; user types ^C in response to this input request. In this case,
; the calling process is aborted by DOS and never returns to this
; procedure. This means that we never get a chance to clear
; "onintstack". The effects of this are that no further output
; will be written to the output file. A possible solution may
; be to chain to the termination vector (int 22h), but this would
; have to done every time "callDOS" is called and not just once
; when script starts up, because DOS fiddles with this vector
; whenever a new process is created, or an old one destroyed.
;
_callDOS proc near
push bp
mov bp,sp
mov bx,[bp+4]
mov es, [bx+10]
mov ax,[bx+8]
push ax
mov dx, [bx+6]
mov cx, [bx+4]
mov ax, [bx+0]
mov bx, [bx+2]
pop ds
pushf ; Fake interrupt
call oldvct21
pushf ; Preserve flags from DOS
push ds
push cs
pop ds
push bx
mov bx,[bp+4]
mov [bx+0],ax
pop [bx+2]
mov [bx+4],cx
mov [bx+6],dx
pop [bx+8]
mov [bx+10],es
pop ax ; Return the flags from the DOS call
pop bp
ret
_callDOS endp
;
; void _Getdate(struct date *)
;
public _Getdate
_Getdate proc near
push bp
mov bp,sp
mov ah, 2Ah
int 21h
mov bx,[bp+4]
mov [bx],cx
mov [bx+2],dx
mov [bx+4],al
pop bp
ret
_Getdate endp
;
; void _Gettime(struct time *)
;
public _Gettime
_Gettime proc near
push bp
mov bp,sp
mov ah, 2Ch
int 21h
mov bx,[bp+4]
mov [bx],dx
mov [bx+2],cx
pop bp
ret
_Gettime endp
_text ends
_data segment word public 'data'
_s@ label byte
_data ends
end